/*
 * Copyright (C) 2008 Universidade Federal de Campina Grande
 *  
 * This file is part of OurGrid. 
 *
 * OurGrid is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free 
 * Software Foundation, either version 3 of the License, or (at your option) 
 * any later version. 
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * for more details. 
 * 
 * You should have received a copy of the GNU Lesser General Public License 
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package org.ourgrid.broker.ui.async.gui.graphical.workers;

/**
 * Class to provide a Bidimensional Array
 */
public class BidimensionalArray<E> {

	private int initialLength;

	private E[ ][ ] arrays;

	private final static String LINE_SEPARATOR = System.getProperty( "line.separator" );

	
	@SuppressWarnings("unchecked")
	public BidimensionalArray( int initialArrayLength ) {

		arrays = (E[ ][ ]) new Object[ initialArrayLength ][ initialArrayLength ];
		this.initialLength = initialArrayLength;
	}


	/**
	 * Inserts a new element at the determinated coordenate. If the coordenate
	 * already exists in this <code>BidimensionalArray</code>, the old
	 * element is replaced by the specified element.
	 * 
	 * @param x_index Represents the "x" position, as a cartesian plane.
	 * @param y_index Represents the "y" position, as a cartesian plane.
	 * @param element The element to be added.
	 */
	public boolean insert( int x_index, int y_index, E element ) {

		needResize( x_index, y_index );

		if ( arrays[x_index][y_index] != null )
			return false;

		arrays[x_index][y_index] = element;
		return true;

	}


	private void needResize( int x_index, int y_index ) {

		if ( x_index >= initialLength - 1 || y_index >= initialLength - 1 )
			resizeArray();
	}


	@SuppressWarnings("unchecked")
	private void resizeArray() {

		int oldLength = initialLength;
		initialLength = 2 * initialLength;

		E[ ][ ] tmp = (E[ ][ ]) new Object[ initialLength ][ initialLength ];
		for ( int x = 0; x < oldLength; x++ ) {
			for ( int y = 0; y < oldLength; y++ ) {
				tmp[x][y] = arrays[x][y];
			}
		}

		arrays = tmp;

	}


	public void insertAtRow( int row, E element ) {

		for ( int i = 0; i < initialLength; i++ ) {
			needResize( row, i );
			if ( arrays[row][i] == null ) {
				arrays[row][i] = element;
				break;
			}
		}

	}


	public void insertAtColumn( int column, E element ) {

		for ( int i = 0; i < initialLength; i++ ) {
			needResize( i, column );
			if ( arrays[i][column] == null ) {
				arrays[i][column] = element;
				break;
			}

		}

	}


	/**
	 * Gets the element at the determinated position. Returns null if the
	 * position is not assigned.
	 * 
	 * @param x_index Represents the "x" position, as a cartesian plane.
	 * @param y_index Represents the "y" position, as a cartesian plane.
	 */
	@SuppressWarnings("unchecked")
	public E get( int x_index, int y_index ) {

		return arrays[x_index][y_index];

	}


	public E remove( int x_index, int y_index ) {

		E ret = get( x_index, y_index );
		arrays[x_index][y_index] = null;
		return ret;

	}


	public void replace( int x_index, int y_index, E element ) {

		arrays[x_index][y_index] = element;

	}


	@Override
	public String toString() {

		String str = "| ";
		for ( int x = 0; x < initialLength; x++ ) {
			for ( int y = 0; y < initialLength; y++ ) {
				str += arrays[x][y] + " | ";
			}
			str += x != initialLength ? LINE_SEPARATOR : "";
		}
		str += " |";

		return str;
	}
}
